﻿namespace HuwmanCode

open System
open HuwmanCode
open NUnit.Framework
open FsUnit

[<TestFixture>]
type ``Action ``() =
    [<Test>]
    member this.``Action.Try - action invokes``() =
        let actionInvokes = ref false
        let action = new Action(fun _ -> actionInvokes := true)
        let compensate = new Action<Exception>(fun e -> ())
        action |> Action.Try(compensate) |> ignore

        !actionInvokes |> should be True

    [<Test>]
    member this.``Action.Try - compensation invokes when action raises exn``() =
        let compensationInvokes = ref false
        let action = new Action(fun _ -> failwith "A big bugger up!")
        let compensate = new Action<Exception>(fun e -> compensationInvokes := true)
        action |> Action.Try(compensate) |> ignore

        !compensationInvokes |> should be True

    [<Test>]
    member this.``Action.Try - returns Some when action invokes without error``() =
        let action = new Action(fun _ -> ())
        let compensate = new Action<Exception>(fun e -> ())
        action |> Action.Try(compensate) |> Option.isSome |> should be True

    [<Test>]
    member this.``Action.Try - returns None when action raises exn``() =
        let action = new Action(fun _ -> failwith "A big bugger up!")
        let compensate = new Action<Exception>(fun e -> ())
        action |> Action.Try(compensate) |> Option.isNone |> should be True

    [<Test>]
    member this.``Action.TryWithRethrow - action invokes``() =
        let actionInvokes = ref false
        let action = new Action(fun _ -> actionInvokes := true)
        let compensate = new Action<Exception>(fun e -> ())
        action |> Action.TryWithRethrow(compensate) |> ignore

        !actionInvokes |> should be True

    [<Test>]
    member this.``Action.TryWithRethrow - compensation invokes when action raises exn``() =
        let compensationInvokes = ref false
        let action = new Action(fun _ -> failwith "A big bugger up!")
        let compensate = new Action<Exception>(fun e -> compensationInvokes := true)
        
        try
            action |> Action.TryWithRethrow(compensate) |> ignore
        with _ -> ()

        !compensationInvokes |> should be True

    [<Test>]
    member this.``Action.TryWithRethrow - exn is reraised when action raises exn``() =
        let exceptionIsReraised = ref false
        let action = new Action(fun _ -> failwith "A big bugger up!")
        let compensate = new Action<Exception>(fun e -> ())
        
        try
            action |> Action.TryWithRethrow(compensate) |> ignore
        with _ -> exceptionIsReraised := true

        !exceptionIsReraised |> should be True